@L|}6CD l0C)HCC WhL/h `CmCDiD`  R@P1  Y0@R !L` D  C D     )16CS S)  C)D1 p p 0 C9DI pCDL~CiCDiD` D  C D     )16CS S)  C)D1 p p }0 C9DI pCDL~CiCDiD` DD˙` d J)L !}D L(( LL()  L| L( S LH 0p n  } CY?  q  L L  ` )} `A! d߰")-݆ "  $G@LLL&0") $G% }H0 3S8`G ȱG ȱG   Gȭ Gȭ GG}GHiH8(()) G$H% `(0 })8` d)L ݆ & LGȘ ݆LL d  ! LL d)N>Q  HH) }  hyhyB q L> Lm JJ  Ln*` dB%' }8  H H` 1 { LL   !L     Hh SY?  q  1L }  !? S   q 1 L   Ll  Lg E`L   !L)  q 1L}) `L0AM݊L݉ ML  N݆LLLNLMLHG!@}1F GȱGLLEEȩÑEȑEEȑE Ed E7EȩE  q} L !,0,0SGɛ L 1 !L EHEh W G gLLSROTCES EERF } G) *Gȩ GȽG GȌd q q G`  8   0G  `D}CEDC0X:Ȣ Y ȱC* ? 0.. , 0%n ?A[ 0 : L`L  `, 0`Y}`piH n0)բY? 08`0 }  0$L GGȽG L `8L`L}8`  05G)݁,G)ȱGȱGHh0})Hh` B! 8`8iiiLE`}E8FEh( l0`ɃLL L8^~jj8jHi hEEEiEȱEiE` dTE} H8EEȱEEȩEh J E8   . m  i`LI!)E1FR}1LJ舩9GIH`LJJ`HGHh l`} S gL   8 rii `дCDCG W  }C  Lq` X٨`DOS SYS IIIIIIIIIIIIIIIC`0 ߩ0}}} HE |||DDOS DOSDOS SYS }}} OO}CDOS SYS} 0`BDELV !B }`LVUQ   ]   TU J ]L!T  #      TU  } L ? .  t`GBJ V~DEHI B V0dV!}QDEHI VF9 ,0 ,0 s0hhL  L` H hDHEh"}DEL8HI   0 HI,0 0  9 .G VLO#},0 L4*IJ`llD1:AUTORUN.SYSNEED MEM.SAV TO LOAD THIS FILE.D1:MEM.SAV J y08 B|DEHI$} V0 0`B;DELV䌚 !B y`@ʆ v s? F0Ξ05: [ BDEHI%} VY8 B V  @  /DE `E:D1:DUP.SYSERROR-SAVING USER MEMORY ON DISKTYPE Y TO &}STILL RUN DOS B;DE J V (` 9 V⪍ ઍ  -'}LLu DEHILV 9 .l 9 .l  `` s$B VBH(}I|DE V BLV nB,DE J V* \*` B V BLVDEHI BLVL)}1u H232435; 1 ;  hh@2 e1i1LHҍ 00) 08 109hh@ Ҡ2e*}1i1232435ޥ<<8} 3E:}DOS ĠǠĠ NOT...COPYRIGHT 1980 ATARIA. DISK DIRECTORY I. FORMAT DISKB. RUN CARTRIDGE J. ,} DISK C. COPY FILE K. BINARY SAVED. DELETE FILE(S) L. BINARY LOADE. RENAME FILE M. RUN AT ADDRESSF. LOCK F-}ILE N. CREATE MEM.SAVG. UNLOCK FILE O. DUPLICATE FILEH. WRITE DOS FILES9!&x#!7&p))'&X*./)L''-؆莟.}R'S  vW DEHHI 1A#! @ ~0ɛ8A0.) ȅ 1 1i/}il ! 1L NO SUCH ITEMSELECT ITEM OR FOR MENU! 0 .{z:*{}.|~ 1 0 00}JB 18L^%|DLl%DIRECTORY--SEARCH SPEC,LIST FILE? # 0 0 n&|D! 1L NOT A DISK FILE1}N !B 1L " 1 !BDED:}:1BJ|DE 1DEBH2}I 1 h0ߢ 0.  0?詛 1 ~0YЛ 1 "L<" "L 3} BL1TYPE "Y" TO DELETE...DELETE FILE SPECCOPY--FROM, TO?OPTION NOT ALLOWED097 FREE SECTORS COPYING---D1:RENA4}MELS.BAS# 0|D .L$A#B#C#JB|DE 1BHIDD#E 1D#0: B5} 1L B#C#C#B# B 1N#$0SYS1}:e#D# d# D# .d#ȽD# d# 𩛙d#X# 1,A#6}PdD#ELO- A.BJdD#E 1 1HH 0hh|DL^%1}:e# Lt% e#dD#EL%7} 1 0 . .0% 1L WILD CARDS NOT ALLOWED IN DESTINATION 0 A.|K@C}//3Hu ξL/L DRIVE TO WRITE DOS FILES TO?WRITING NEW DOS FILESTYPE "Y" TO WRITE DOS TO DRIVE 2.?}D2:DOS.SYSERROR - NOT VERSION 2 FORMAT. , &* բ( 1L `[) 0NΞ 0 L1M) 1@} L BAD LOAD FILELOAD FROM WHAT FILE?) 0 0#B 1L WHAT FILE TO LOCK?) 0 0$B 1L WHAT FILE TO UNLOCK?DUA}P DISK-SOURCE,DEST DRIVES?TYPE "Y" IF OK TO USE PROGRAM AREACAUTION: A "Y" INVALIDATES MEM.SAV. h B}  `)  <0 2 2 0  ,   ,,ޢ* 1L ,K* 1 ~0 0C}FINSERT BOTH DISKS, TYPE RETURNERROR - DRIVES INCOMPATIBLE., 1 ~038  , 1L D}, &*  Lz+, 0 , 1 ~0 +,0 ,L+ ,mm  v,"ǭE}0Ξ, 05,Lt+L +,Hh` NOT ENOUGH ROOMINSERT SOURCE DISK,TYPE RETURNF}INSERT DESTINATION DISK,TYPE RETURN`    `L,8,0( rG} v,(`ߢ) 1* 1 ~0Y`hhL S SL1) 8`NAME OF FILE TO MOVE?- 0 0|DLtH}% A., 1 <0 0 .@L# .BJ 1  DEHIB V L1 ,5 1 <0,L. I} JB|,A#Pd#DE 1 HI BDEHHII 1 B 1 , 1 <0,0Lf- B VJ},A#P, 1 <0 0L#L ߢ) 1* 1 ~0Yj383}mm ݭK}}`8}``|* ? ɛ,`|:(|/ 1L `DESTINATION CANT L}BE DOS.SYS0 0H{ $22Δ $28/L /) $2 Π $2 0 ξM}hAΞB,0 J 1 BޝDEHI,HDE 1HIHIDELSAVE-N}GIVE FILE,START,END(,INIT,RUN)O X0 1`BDEPHI V` X0H 1 L O}0 0 1L0`PLEASE TYPE 1 LETTER,0`hhL <0 1L0LA1 ,;ɛ7,"ɛ:ݦ1ݥP}A"D|ݤD|ȩ:|ȩ|ɛ,,(/+.ީ1 1,ɛ`轤{Q}NAME TOO LONG B VL ` L1I H1EӝDL1|mDiE` V0`8d/8 i:"2!22 1R} L ERROR- 173ɛ+,' 20*.. өw2 1``2TOO MANY DIGITSINVALIDS} HEXADECIMAL PARAMETER800 0 8 00`,0'D800H,ɛh`2L1NEED D1 THRU D4;uT} HEXADECIMAL PARAMETER800 0 8 00`,0'D800H,ɛh`2L1NEED D1 THRU D4;u;*************************************;; ATARI 1050 DISK DRIVE INTERFACE;; COPYRIGHT 1985 (C) BY EMC;;*****************V}*********************;;;SYSTEM CONSTANTS;;DRA=$0280;6532 DATA REGISTERDDRA=$0281;DATA DIREC. REG ADRB=$0282;W}DATA REGISTER BDDRB=$0283;DATA DIREC REG BRTDE=$0284;READ TIMER DISABLE IRQWT24E=$029F;WRITE TIMER ENABLE INT.WTX}64D=$0296;WRITE TIMER DISABLE INT.;**************************************;; BIT ASSIGNMENTS;PORT A:; D0:SELECT SY}WITCH; D1:SELECT SWITCH; D2:NOT USED; D3:N MOTOR CONTROL; D4:WRITE PRE COMPENSATE; D5:FDC DOUBLE DENZ}SITY; D6:6532 IRQ; D7:FDC DATA REQUEST;;PORT B:; D0:DATA OUT; D1:VCC READY; D2:NS04; D3:NS03[}; D4:NS02; D5:NS01; D6:DATA IN; D7:CMD;;**************************************STREG=$0400;FDC STATU\}S REGISTERCMDREG=$0400;FDC COMMAND REGISTERTRKREG=$0401;FDC TRACK REGISTERSECREG=$0402;FDC SECTOR REGISTERDTAREG]}=$0403;FDC DATA REGISTER;PAGE ZERO VALUESZERO=$00;START OF PAGE ZERO;;GLOBAL VARIABLES;THESE SHOULD BE SET BY O^}NE ROUTINE;BUT CAN BE READ BY ALLORG0;CSELXXDS2;COMMAND CONTINUATION;VECTOR;INITIALIZED TO POINT;TO CMDN_}AK. USRE RESETS;TO POINT TO OWN;COMMAND DECODE;ROUTINE;;VARIABLES USED BY GET;GPNTDS2;GET POINTERGCNTDS`}1;GET COUNTFLAGDS1;USED BY GET;;VARIALBES USED BY PUT;;VARIABLES USE BY CSUM;CHKSUMDS1;CHECKSUM 1 BYTE;;VARIa}ABLES USED BY CLRMEM;PNTRDS2;MEMORY POINTER 2 BYTES;;VARIABLES USED BY READ;RLENDS1;LENTH OF DATA TO READ;;VARIb}ABLES USED BY SEND;SLENDS1;LENTH OF BUFFER TO SEND;;VARIALBES USED BY RCMDFRM;;************************************c};; CMDFRM:DEVICE SELECT CODE; +1:COMMAND BYTE; +2:DAUX1 FROM SIO; +3:DAUX2 FROM SIO; +4:CHECKSUM FROM SId}O;;************************************;CMDPNTDS2;POINTER TO COMMAND BUFFCMDFRMDS5;COMMAND FRAM BUFFER;TRACKDSe}1;CURRERT TRACKTADRESDS6;SIX BYTES TRACK ADDRESSNTRKDS1;NEW TRACK TO READNSECDS1;NEW SECTOR TO READSTRADRDS2f};POINTER TO START LOADING;PROGRAM DATA INTO RAMTCDS1;TIMER COUNT FOR 5 SECMFLAGDS1;MOTOR ON FLAGTINBDS1;TRACKg} IN BUFFER;STATDS4;;;************************************;; STATUS BYTES:; STAT:; STAT+1:; STAT+2:; STAT+3:;;h}************************************;;TEMPDS1;TEMP BYTE LOCATIONBPNTDS2;SECTOR BUFFER POINTERLENTHDS1;DATA PARAi}METER FOR SENDRTRYSDS1ECDS2;ERROR COUNT LOCATIONCONFIGDS12;12 BYTES FOR DATA CONTROLDRCLSDDS1;FF WHEN CLOSEDj}SECTDS1TRCKDS1BASEDS2MLPLRDS1MCANDDS1PRODDS2;16 BIT PRODUCTBPNT1DS2;2 BYTESTRKCHDS18;18 BYTE SECTORk} OK ARRAY;;GLOBAL;VARIABLES USED BY ACTION RUNTIME;LIBRARY FUNCTIONS;SIGNDS1;ONE BYTE FOR SIGN INFOATMPDS2;TEMP l}LOCATION FOR MATH;BUFF=$2000;256 BYTE BUFFER I/O;ORG$4000;ADDRESS TO LOAD INTO RAM;WHEN USING DEBUG, ETC.LOCm}$E000;RUN LOCATION FOR CODE;THIS ALLOWS US TO ROM CODE;;**************************************;;JUMP VECTOR TABLE; n}THIS IS WHERE USER PROGRAMS CALL TO; ACCESS THE VARIOUS UTILITIES IN THIS; PROGRAM; THESE WILL BE THE ONLY DOCUMENTED; ENo}TRY POINTS INTO THE SYSTEM;;**************************************;VECTABJMPSTART;COLDSTARTNAKVJMPNAK;SEND NOT ACKp}KNOLEDGEERRVJMPERR;SEND ERROR CODE BACKACKVJMPACK;SEND ACK BACKCMPLVJMPCMPLT;SEND COMPLETE BACKDELVJMPDELAY;Dq}O 250 USEC DELAYGETVJMPGET;GET DATA FROM SERIAL BUSPUTVJMPPUT;PUT BYTE TO ATARICSUMVJMPCSUM;COMPUT CHECKSUMREADVr}JMPREAD;GET DATA FROM ATARI;ALSO CHECKS THE CHECK SUMSENDVJMPSEND;SEND BUFFER BACK TO ;ATARI WITH A CHECKSUMFs}INTVJMPFINT;FDC FORCE INTERRUPTMULTVJMPMULT;PERFORM 8 BY 8 MULTIPLYTRK0VJMPTRK0;RECAL HEAD POSITIONWT5MSVJMPSWAt}IT;5 MSEC DELAYSKTKVJMPSKTK;SEEK TRACKNTSVJMPNTS;CALCULATE NEW TRACK FROM;DATA IN COMMAND FRAMERSECVJMPRSEC;u}READ SECTOR ON CURRENT;TRACKVSECVJMPVSEC;VERIFY SECTOR ON;CURRENT TRACKWSECVJMPWSEC;WRITE SECTOR TO CURRENTv};TRACKRDTKVJMPRDTK;READ ALL SECTORS ON;CURRENT TRACK AND;PUT THEM IN TRACK;BUFFERSBPNTVJMPSBPNT;SET SECw}TOR BUFFER;POINTERRDSCVJMPRDSC;SEND DATA IN TRACK;TRACK BUFFER THAT;CORRESPONDS TO;SECTOR NUMBERMOONVJMx}PMOON;TURN MOTOR ONMOOFFVJMPMOOFF;TURN MOTOR OFF;VCMDXTJMPCMDXITVCMDNKJMPCMDNAKVCMDERJMPCMDERR;;ACTION RUNTy}IME VECTORS;LSHVJMPLSH;LEFT SHIFTRSHVJMPRSH;RIGHT SHIFTMLTVJMPMLTI;MULTIPLYDIVVJMPDIVI;DIVIDESARGVJMPSARGz}S;PASS ARGUMENTSLOWVJMPLOWB;RETURN LOW BYTEHIVJMPHIB;RETURN HIGH BYTE;LIST-L;;********************************{}*****;; RUNTIME LIBRARY FUNCTION FOR ACTION!;; RSH; LSH; MULT; DIV; MOD; SARGS;;**********************************|}***;LSHPROC;;THIS ROUTINE WILL SHIFT A NUMBER LEFT;:SHIFT=$84;NUMBER OF BYTES TO SHIFT:MSB=$85;MOST SIG BYTE TO}} SHIFT;LDY:SHIFT;ARE WE SHIFTING BY ZEROBEQ:LSHXT;YES, JUST EXITSTX:MSB;STORE MOST SIGNIFICANT BYTE:LOOPASLA~};SHIFT LSBROL:MSB;SHIFT MSBDEY;DECREMENT SHIFTBNE:LOOP;KEEP ON GOINGLDX:MSB;RETURN MSB IN XREG:LSHXTRTSEPR}OC;;RSHPROC;RIGHT SHIFT FUNCTION;:SHIFT=$84;AMOUNT TO SHIFT BY:MSB=$85;MOST SIG BYTE;LDY:SHIFT;IS SHIFT = }0?BEQ:RSHXT;YES EXITSTX:MSB:LOOPLSR:MSB;SHIFT MOST SIG BYTERORA;SHIFT LSBDEY;DECREMENT SHIFTBNE:LOOPLD}X:MSB;RETURN MSB IN X REG:RSHXTRTS;SSNGPROC;SET SIGN;:OP3=$86;LDYSIGNBPL:SS08SS1STA:OP3STX:OP3+1S}ECLDA#$00SBC:OP3TAYLDA#$00SBC:OP3+1TAXTYA:SS08RTSEPROCSMOPSPROC;:OP1=$82:OP2=$84:OP3=$86;}STXSIGNCPX#$00BPL:SM11JSRSS1:SM11STA:OP1STX:OP1+1LDA:OP2+1BPL:SM15TAXEORSIGNSTASIGNLDA:OP2}JSRSS1;SET SIGNSTA:OP2STX:OP2+1:SM15LDA#$00STA:OP3+1RTSEPROC;MLTBPROC;:OP1=$82:OP2=$84:OP3=$}86;BEQ:MB16DEXSTXATMP+1TAXBEQ:MB16STXATMPLDA#$00LDX#$08:MB20ASLAASLATMPBCC:MB19ADCATMP+1:}MB19DEXBNE:MB20CLCADC:OP3+1STA:OP3+1:MB16LDA:OP3LDX:OP3+1RTSEPROC;MLTIPROC;:OP1=$82:OP2=$84:}OP3=$86;JSRSMOPSLDX:OP1BEQ:MI22STXATMPLDX:OP2BEQ:MI22DEXSTXATMP+1LDX#$08:MI24ASLAROL:OP3+1}ASLATMPBCC:MI23ADCATMP+1BCC:MI23INC:OP3+1:MI23DEXBNE:MI24:MI22STA:OP3LDA:OP1LDX:OP2+1JSRMLTB}LDA:OP1+1LDX:OP2JSRMLTBJMPSSNGEPROC;;DIVIDE TWO NUMBERS;DIVIPROC;:OP1=$82:OP2=$84:OP3=$86;JSR}SMOPSLDA:OP2+1BEQ:DI27LDX#$08:DI29ROL:OP1ROL:OP1+1ROL:OP3+1SECLDA:OP1+1SBC:OP2TAYLDA:OP3+1SB}C:OP2+1BCC:DI28STA:OP3+1STY:OP1+1:DI28DEXBNE:DI29LDA:OP1ROLALDX#$00LDY:OP1+1STY:OP3JMPSSNG:}DI27LDX#$10:DI32ROL:OP1ROL:OP1+1ROLABCS:DI30CMP:OP2BCC:DI31:DI30SBC:OP2SEC:DI31DEXBNE:DI32ROL}:OP1ROL:OP1+1STA:OP3LDA:OP1LDX:OP1+1JMPSSNGEPROC;; DO MOD FUNCTION;MODIPROC;:RMDR=$86;REMAINDER}JSRDIVI;DO DIVISIONLDA:RMDR;RETURN LO BYTE IN ACCLDX:RMDR+1;RETURN HI BYTE IN X REGRTSEPROC;; PASS PARAMETERS} BETWEEN FUNCTIONS;SARGSPROC;:PRAMS=$A0;SIXTEEN BYTES:TEMP=$84;TWO BYTES:PPNT=$82;STA:PRAMS;STORE PARAMS }STORED INSTX:PRAMS+1;A,X,Y REGISTERSSTY:PRAMS+2CLC;PREPARE TO ADDPLA;POP RETURN ADDRESS FROM STACKSTA:TEMP;S}TORE IN TEMP LOCATIONADC#$03;CALCULATE NEW RETURN ADDRESSTAY;TO BRANCH AROUND POINTER TOPLA;PASSED PARAMETERSSTA}:TEMP+1;$0085ADC#$00PHA;PUSH NEW RETRUN ADDRESS ON STACKTYAPHALDY#$01;POINT TO PARAMETERS AREALDA(:TEMP),Y};LOW BYTE OF POINTERSTA:PPNTINYLDA(:TEMP),Y;HIGH BYTE OF POINTERSTA:PPNT+1INYLDA(:TEMP),Y;NUMBER OF PARAMET}ERSTAY:LOOPLDA:PRAMS,Y;TRANSFER FROMSTA(:PPNT),Y;TEMPORARY TO LOCALDEY;PARAMETER AREABPL:LOOPRTSEPROC;;}**************************************; THESE ARE OTHER USEFUL ACTION!; FUNCTIONS;;**************************************};;RETRUN LSB OF A CARD;HIBPROC;:RES=$A0;STX:RESRTSEPROC;;RETURN HIGH BYTE OF A CARD;LOWBPROC;:RES=$}A0;STA:RESRTSEPROC;;LINKD2:DD7M1.ASM050 DISK DRIVE INTERFACE;; COPYRIGHT 1985 (C) BY EMC;;*****************2;;**************************************;; THIS IS WHERE WE ENTER WHEN PROCESSOR; IS RESET.; PERIPHERAL DEVICES ARE INIT }IALIZED; MEMORY IS CLEARED; BACKGROUND PROCESSING, IF ANY IS; STARTED;;**************************************;STARTLD }X#$FFTXS;SET THE STACK POINTER TO;TOP OF STACKJSRCLRMEM;CLEAR MEMORYJSRCLRZER;CLEAR PAGE ZERO;LDA#LOW CM }DNAK;INIT USER COMMANDSTACSELXX;DECODE VECTOR TO COMANDLDA#HIGH CMDNAK;NAKSTACSELXX+1LDA#$FFSTATINBLDA#$ }10;MAX OF 16 SEC TIMEOUTSTASTAT+2LDA#$10STASTAT;TELL THE WORLD WE ARE HERELDA#$3C;SET PORT A FOR INPUTSTAD }DRA;USER MAY IF HE/SHE CHOOSESLDA#$3DSTADDRBLDA#%00111101STADRBLDA#$FFSTADRALDA#$00STAEC;INIT ERROR } COUNT FOR DEBUGLDA#40;DRIVE CONFIG INITIAL (STDRD)STACONFIG;40 TRACKS PER SIDELDA#18STACONFIG+3;18 SECTORS P }ER TRACKLDA#128STACONFIG+7STALENTH;SECTOR LENGTHLDA#$40STACONFIG+8CLD;CLEAR DECIMAL MODEJSRMOON;TURN } ON MOTORJSRTRK0;SEEK TRACK 0LDA#15STANTRKJSRSKTK;SEEK TRACK 15JSRTRK0;SEEK TRACK 0JSRI5SEC;INIT 5 SEC }OND TIMERBKGRNDLDA#2;BIT MASKBITDRB;TEST CMD LINEBPLBK001;CMD NOT HIGHBNEBK001;COMPUTER NOT ONJSRRCMDFRM; }GET COMMAND FRAMEJSRI5SEC;RE INIT 5 SEC TIMERBK001JSRDRCHK;CHECK DOOR STATUSLDAMFLAGCMP#$00BEQBKGRNDJSRCK }5S;CHECK 5 SECOND TIMERBCCBK002JSRMOOFF;TURN OFF MOTOTLDAWT64DLDA#$00STAMFLAGBK002JMPBKGRND;JUMP TO BACK }GROUND;ROUTINE;;**************************************;; DRCHK: CHECK DOOR STATUS;; ENTRY: NONE; EXIT: NONE; RE }GISTERS USED: ACCUMULATOR;;**************************************DRCHKBITSTREGBPLDRCHK1;DOOR CLOSEDBITDRCLSDBP }LDRCKXT;STILL OPEN, EXITLDA#0;JUST OPENEDSTADRCLSDJMPDRCKXTDRCHK1BITDRCLSDBMIDRCKXT;STILL CLOSED, EXITLD }A#$FF;JUST CLOSEDSTADRCLSDJSRMOONJSRI5SECDRCKXTRTS;**************************************;; DELAY: ABOUT 25 }0USEC;;**************************************;DELAYPHA;SAVE ACCUMULATORLDA#42DEL01SECSBC#$01;DECREMANT ACCBN }EDEL01PLARTS;;;**************************************;; GET DATA FROM SERIAL BUS;; ENTRY:A-REG =# OF BYTES TO GET }; :BPNT CONTAIN ADDRESS OF BUFFER; EXIT:DATA IN BUFFER; :$A0 CONTAINS STAUTUS; :$A1 CONTAINS CHECKSUM;; RE }GISTERS USED:ACCUMULATOR,X,Y; :USES BPNT;**************************************;GETPROC;:STATUS=$A0:C }KSUM=$A1;STAGCNT;SAVE BYTE COUNTLDY#$00STYFLAG;INIT CHECKSUM FLAG:GET01BITDRA;CHECK FOR TIME OUTBVCDITOU }TBITDRB;WAIT FOR START BITBVC:GET01;LOOP IF NO OVERFLOWSEC;SET CARRYLDA#$80;A := $80LDX#$06;:GET02DEX; }BNE:GET02;DELAY LOOPLB80LDX#$06;:GET03DEX;BNE:GET03;DELAY LOOPNOPNOPNOP;TIMINGBITDRBBVC:GET04;J }MP AND SET CARRYCLCBCC:GET05;JMP WITH CARRY CLEAR:GET04SECNOP:GET05RORABCCLB80LDXFLAGBNE:GETXITSTA(B }PNT),YINYCPYGCNT;DECREMENT BYTE COUNTBNE:GET01;KEEP GOING, MORE DATALDX#$FFSTXFLAG;NOW WE GET THE CHECKSUM }BNE:GET01:GETXITSTA:CKSUM;SAVE CHECKSUMLDA#0STA:STATUSLDAWT64D:GETXTRTS;;DO THIS IF THERE IS A TIMEOUT;DI }TOUTLDA#$01STA:STATUS;TIMEOUT STATUS RETURNEDLDAWT64DJMP:GETXTEPROC;;;************************************** };; SET TIME OUT:;;**************************************;STMOSTAWT64DSTAWT24ERTS;;;;************************* }*************;; PUT:; SEND THE BYTE IN THE ACCUMULATOR; TO THE ATARI COMPUTER;; ENTRY:A<-- BYTE TO SEND; EXIT: N }ONE;; REGISTERS USED:ALL PRESERVED;;;**************************************;;PUTPROC;:DATA=$A0;DATA TO TRANSMIT }:SAVEX=$A1;SAVE AREA FOR X REG:SAVEY=$A2;SAVE AREA FOR Y REG;STA:DATASTY:SAVEYSTX:SAVEXLDY#$08LDA#$FE }ANDDRBSTADRBINC:SAVEXPUT93ROR:DATABCCPUT90LDA#$01ORADRBBNEPUT91PUT90LDA#$FEANDDRBNOPPUT91LD }X#$05PUT92DEXBNEPUT92STADRBDEYBNEPUT93LDX#$06PUT94DEXBNEPUT94NOPDEC:SAVEXLDA#$01ORADRBSTA }DRBLDX#$05PUT95DEXBNEPUT95LDX:SAVEXLDA:DATALDY:SAVEYRTSEPROC;;;;************************************ }**;; ACK:; SEND ACKNOLEGDE BACK TO ATARI;; ENTRY:NONE; EXIT:NONE;; REGISTERS USED:; ACCUMULATO }R;;**************************************;ACKLDA#'A';LOAD ACK CODEJSRPUT;SEND IT TO THE ATARIRTS;;************ }**************************;; NAK:; SEND NOT ACKNOLEGED BACK TO ATARI;; ENTRY:NONE; EXIT:NONE;; REGISTERS USED: }; ACCUMULATOR;;**************************************;NAKLDA#'N';LOAD NAK CODEJSRPUT;SEND IT TO TH }E ARARIRTS;;**************************************;; ERR:; SEND ERROR BACK TO ATARI;; ENTRY:NONE; EXIT:NONE; }; REGISTERS USED:A;;**************************************;ERRLDA#'E';LOAD ERROR CODEJSRPUT;SEND IT TO THE ARAR }IRTS;;**************************************;; CMPLT:; SEND PROCESS COMPLETE CODE;; ENTRY: NONE; EXIT: NONE; }; REGISTERS USED:A;;**************************************;CMPLTLDA#'C';LOAD COMPLETE CODEJSRPUT;SEND IT TO THE }ATARIRTS;;;**************************************;; CSUM:; COMPUTE THE CHECKSUM;; ENTRY:A CONTAINS VALUE TO AD }D TO CSUM; EXIT:NONE;;**************************************;CSUMPHA;SAVE ACCUMULATORCLC;PREPARE TO ADDADCCHKSU }MADC#$00STACHKSUMPLA;RECOVER ORIGINAL VALUERTS;;**************************************;; CKSM:;; COMPUT }E THE CHECKSUM ATARI STYLE;; ENTRY:X REG NUMBER OF VALUES TO CHK; :BPNT=ADDRESS OF STRING; :CHKSUM IS IN REG } A; EXIT:CARRY SET IF BAD CHECKSUM;; REGISTERS USED:A,X,Y;; MEMORY USE:; ONE BYTE ON PAGE ZERO; } CHKSUM;;**************************************;CKSMPROC;:CHKSM=$A0;STA:CHKSM;SAVE CHECKSUMSTXGCNT;SE }T UP LOOP COUNTERLDY#$00;ZERO INDEXLDA(BPNT),Y;FIRST NUMBERINY;POINT TO NEXT VALUECKSM01CLCADC(BPNT),Y;SUM WI }TH CHECKSUMADC#$00;ADD CARRY IF ANYINYCPYGCNT;END OF STRING?BNECKSM01SECSBC:CHKSM;EQUAL TO CHECKSUM?STA }:CHKSM;RETURN 0 IF EQUALRTSEPROC;;**************************************;; CLRMEM:; CLEAR MEMORY PAGES 2 TO $ }0F;; ENTRY:NONE; EXIT:PAGES 2 TO 15 FILLED WITH $00; ; REGISTERS USED:A,X,Y;; MEMORY USED:2 BYTES PAGE ZERO;;* }*************************************;CLRMEMLDA#HIGH BUFF;ON PAGE ZERO TO POINTSTAPNTR+1;TO MEMORY TO CLEARLDA#LO }W BUFF;CLEAR ACCUMSTAPNTR;SET UP INDIRECT POINTER;LDY#$00;INIT INDEX REGISTERCLMEM1STA(PNTR),YINY;POINT TO NE }XT BYTEBNECLMEM1INCPNTR+1;INC MEMORY POINTERLDXPNTR+1CPX#$40;END OF MEMORY TO CLEAR (2K)BNECLMEM1;CONTINUE }UNTILL DONERTS;;**************************************;; CLRZER:; CLEAR PAGE ZERO;; ENTRY:NONE; EXIT: PAGE ZE }RO FILLED WITH $00;; REGISTERS USED :A,X;;**************************************;CLRZERLDA#$00;SET UP TO CLEAR MEM }TAX;INIT INDEX REGISTERCLZER1STAZERO,X;CLEAR MEMORY BYTEINXCPX#$80BNECLZER1;CONTINUE TILL DONERTS;;******* }*******************************;; SDSTAT:; SEND STATUS TO THE ATARI COMPT;; ENTRY:NONE; EXIT: STATUS SENT TO ATAR }I;; REGISTERS USED:A,X;; MEMORY USED:SENDS STATUS BLOCK FROM; PAGE ZERO SEE ABOVE;; FORMAT OF STATUS A }RRAY:; BYTE 0:COMMAND STATUS; BYTE 1:HARDWARE STATUS; BYTE 2:TIMEOUT; BYTE 3:UNUSED;; COMMAND STATUS:; BIT0=1 IND }ICATES INVALID CMD FRM REC; BIT1=1 IND. INVALID DATA FRAME REC.; BIT2=1 IND. PUT WAS UNSUCCESSFUL; BIT3=1 IND. DISKET IS W }RITE PROTECTED; BIT4=1 IND ACTIVE STANDBY;; HARWARE STATUS = STAT REG OF 1793;; TIME OUT = MAX TIME HANDLER TO USE;;; }**************************************;SDSTATLDA#$00;INITIALIZE CHECKSUMSTACHKSUMTAX;INIT INDEX REGISTERLDASTRE }G;LOAD STATUS REGISTERSTASTAT+1SSTAT1LDASTAT,X;LOAD BYTE FROM;STATUS ARRAYJSRCSUM;CALCULATE CHECKSUM FOR XMIT }JSRPUT;SEND IT TO ATARIINXCPX#$04;SENT ALL FOUR BYTES?BNESSTAT1;LDACHKSUM;LOAD CHECK SUMJSRPUT;SEND IT }TO ATARI TOORTS;RETURN;;**************************************;; READ:; FILLS BUFFER ON PAGE TWO WITH; 256 } BYTES OF DATA SENT BY; ATARI;; ENTRY:ACC=LENTH (0=256 BYTES); :BPNT= BUFFER AREA TO PUT DATA; EXIT: BUFFER FI }LLED WITH DATA; : $A0 STATUS OF OPERATION; : 0=OK; : 1=TIMEOUT; : 2=CHECKSUM ERROR;; REGISTERS USED:A,X },Y;; MEMORY USED:PAGE 2;;**************************************;READPROC:CHKS=$A1;CHECKSUM RETURNED FROM GET:STAT }US=$A0;STATUS RETURNED BY GET:LEN=$A2;LENTH OF BUFFER TO SEND;STA:LENJSRGET;GET DATA FROM SIO BUSLDA:STATUS };CHECK STATUSBNE:RDXITLDA:CHKSLDX:LEN;CHECK LEN BYTESJSRCKSM:RDXITRTSEPROC;;***************************** }*********;; SEND:; SEND DATA IN PAGE 2 BUFFER BACK; TO THE ATARI COMPUTER;; ENTRY:BPNT POINTS TO DATA TO SEN }D; EXIT :DATA SENT TO ATARI;; REGISTERS USED:A,Y;; MEMORY USED:PAGE 2 AS MEMORY BUFFER; :$A4;********** }****************************;SENDPROC;:LEN=$A4STA:LENLDA#$00;INITIALIZE CHECKSUMSTACHKSUMTAY;INITIALIZE I }NDEX REGISTER:SEND1LDA(BPNT),Y;LOAD DAT FROM BUFFJSRCSUM;CALCULATE CHECK SUMJSRPUT;SEND DATA TO ATARIINY;NEXT }MEMORY LOCATION TO SENDCPY:LEN;COMPARE TO LENTH TO SENDBNE:SEND1;SENT ALL 256 BYTES?;LDACHKSUM;LOAD CHECKSUMJS }RPUT;AND SEND IT ON ITS WAYRTS;DONEEPROC;;**************************************;; RCMDFRM:; RECIEVE COMMAN }D FRAME;; ENTRY:NONE; EXIT: NONE;; REGISTERS USED:A,X;; MEMORY USED:COMMAND FRAME BUFFER;;********************** }****************;RCMDFRMPROC:STATUS=$A0;GET STATUS;LDA#$FFJSRSTMO;;FILL COMMAND FRAME BUFFER;LDA#LOW CMDF }RMSTABPNTLDA#HIGH CMDFRMSTABPNT+1LDA#$04;GET 4 BYTES FROM ATARIJSRREAD;GET DATA;;WAIT FOR CMD LINE TO GO H }IGH;RCF002BITDRB;MONITOR CMD LINEBMIRCF002;STILL LOW KEEP WAITING;;CMD LINE HIGH, CHECK CHECK SUM;LDA:STATUS; }CHECK STATUSBNERCFERR;BRANCH ON ERROR;LDADRA;READ PORT AAND#$01STATEMPLDADRALSRAAND#$01EORTEMPST }ATEMPLDADRAAND#$01EOR#$01ASLAORATEMPCLCADC#$31;ASCII FOR DRIVE NUMBERCMPCMDFRM;THIS DEVICE REQUESTE }D?BNERCFERR;NO GO BACK AND WAIT; OK WE GOT A COMMAND, LETS GO AND; DECODE ITJSRCMDSEL;DECODE COMMAND; WE RETURN } HERE AFTER PROCESSING; THE COMMANDRCFERRRTS;RETURN TO IDLE CONDITIONEPROC;;**************************************; } CMDSEL:; THIS IS WHERE WE DECODE THE; COMMAND THAT WE HAVE JUST GOT; ENTRY:VALID COMMAND FRAME IN; } COMMAND FRAM BUFFER; EXIT:COMMAND PROCESSED; MEMORY USED:COMMAND FRAME BUFFER; REGISTERS USED:A,X;***************** }*********************;RECOGINIZED COMMANDS:RD=$50;RECEIVE DATA FROM ATARIRDV=$57;RECEIVE AND VERIFY DATAWRT=$52 };SEND DATA TO ATARISTATUS=$53;SEND STATUS TO ATARIRCONFIG=$4E;READ DRIVE CONFIGWCONFIG=$4F;WRITE DRIVE CONFIGFO }RMAT=$21;FORMAT DISKUPLOAD='u';$75 UPLOAD PROGRAM DATARUN='r';$72 RUN PROGRAMSETADR='s';$73 SET ADDRESS LOADG }TRACK='g';$67 seek new trackCFRMAT='c';$63 custom format a track;CMDSELPROC;:STATUS=$A0;STATUS FROM GET;LDA }MFLAG;CHECK MOTOR ON FLAGBNEC01JSRMOON;TURN ON MOTOTJSRSWAITJSRSWAITC01LDACMDFRM+1;LOAD COMMANDCMP#RD; }DO WE GET DATA FROM ATARIBEQCSEL00;YESCMP#RDV;READ WITH VERIFY?BNECSEL01;NO READ, TRY NEXT COMMAND;RECIEVE DATA } FROM COMPUTERCSEL00JSRNTS;CALCULATE NEW SECTORLDANSEC;LOAD SECTOR NUMBERJSRSBPNT;SET BUFFER POINTERJSRACK;S }END ACKNOLEDGELDALENTH;LENTH OF BUFFER TO RECIEVEJSRREAD;READ DATA FROM ATARILDA:STATUS;GET STATUSCMP#$02BNE }:CS001JMPCMDERR;COMMAND ERROR:CS001CMP#$01BNE:CS002;TIMEOUT ERROR?JMPCMDNAK:CS002JSRACKJSRSKTK;SEEK TRA }CKLDANSECJSRWSECBITSTREG;WRITE PROTECT?BVCC0B;NO PROTECTJSRERR;PROTECTED, SEND ERRORJMPC0A;DON'T VERIF }YC0BLDACMDFRM+1;LOAD COMMANDCMP#$57;READ WITH VERIFY?BNEC0A;NO VERIFYLDANSECJSRVSEC;VERIFY READC0ALDA }#$FFSTATINB;NO DATA IN TRACK BUFFERCM0002JSRCMPLT;SEND COMPLETEJMPCMDXIT;EXIT FROM COMMAND PROCESS;CHECK FOR S }END DATACSEL01CMP#WRT;SEND DATA TO ATARI?BNECSEL02;NO, TRY NEXT COMMAND; SEND DATA FRAME BACK TO ATARIJSRACK };IF THE PERIPHERAL HAS TO DO SOMETHING;TO GET THE DATA, IT WOULD DO IT HEREJSRNTS;CALCULATE NEW TRACK/SECTORJSRSKTK };FIND THE TRACK TO READ FIRSTBCSBOUNCE;COMMAND NOT ACKNOLEDGEDJSRRDTK;READ TRACKLDXNSEC;SET INDEX TO SEC TABLED }EXLDATRKCH,XBPLOKSECJSRERROKSECJSRCMPLTJSRRDSCJMPCMDXIT;EXIT FROM COMMAND PROCESSBOUNCEJSRERR;SEND ERR }OR TO ATARIJMPCMDXIT;JUST QUIT; IS IT A REQUEST FOR STATUSCSEL02CMP#STATUS;IS IT STATUSBNECSEL03;NO, TRY NEXT }COMMAND;SEND STATUSLDACONFIG+5;GET DENSITY CONFIGAND#$04;MASK FOR DENSITYASLAASLAASLA;SET BIT 5 FOR DENS }ITYSTASTATLDA#$FF;FF INTO STAT+1?STASTAT+1LDA#$E0;SET TIMEOUTSTASTAT+2LDA#$24;WHO KNOWS WHY?STASTAT+3 }JSRACKJSRDELAY;WAIT BEFORE SENDING COMPLTJSRCMPLT;SEND COMPLETEJSRSDSTAT;SEND STATUSJMPCMDXIT;EXIT FROM CO }MMAND PROCESS;READ CONFIGURATION FROM DRIVECSEL03CMP#RCONFIG;READ CONFIG?BNECSEL04;NO, TRY NEXT COMMAND;JSRDE }LAYJSRACK;ACKNOWLEDGE CMDJSRDELAY;WAIT TO SEND CMPLTJSRCMPLT;SEND OPERATION COMPLETELDALENTHPHA;SAVE LENGT }H ON STACKLDA#12;12 BYTES TO SENDSTALENTHLDA#LOW CONFIGSTABPNT;POINTER TO DATA TO SENDLDA#HIGH CONFIGSTAB }PNT+1LDALENTHJSRSEND;SEND CONFIG TO ATARIPLASTALENTH;RESTORE LENTHJMPCMDXIT;WRITE CONFIGURATION TO DRIVE }CSEL04CMP#WCONFIG;WRITE CONFIG?BNECSEL05;NO, TRY NEXT COMMANDJSRACK;ACKNOWLEDGE CMDLDA#$FFJSRSTMO;SET TIM }E OUTLDA#$0C;SET TO READ 12 BYTESLDX#LOW CONFIG;SET POINTER BPNTSTXBPNTLDX#HIGH CONFIG;STORE DATASTXBPNT+1 };JSRREAD;READ DATA FROM SERIAL BUSLDA:STATUSCMP#$02BNEC4A10JMPCMDERRC4A10CMP#$01BNEC4A11JMPCMDNAKC4 }A11JSRDELAYJSRACKJSRDELAYJSRCMPLT;SEND OPERATION COMPLETEJMPCMDXITLIST*CSEL05CMP#FORMAT;FORMAT?BEQC }SEL5JMPCSEL06;NO NEXT COMMAND!!CSEL5JSRACKJSRSFRMATJMPCMDXIT;LIST-L;************************************** };;THESE ARE SPECIAL COMMANDS FOR USERS;TO LOAD THEIR OWN PROGRAMS UP TO THE;DUPLICATOR BOARD. THIS ALSO PUTS LESS;BURDEN }ON US AS HACKERS WILL LOVE TO;MESS WITH THE DRIVE;;**************************************;CSEL06CMP#SETADR;SET START }ADRESS?BNECSEL07;NO, NEXT COMMAND;;THE START ADDRESS IS CONTAINED IN;AUX1 AND AUX2 OF THE COMMAND FRAME;JSRDELAY; }WAIT JUST A BITJSRACKLDACMDFRM+2;LOAD AUX1STASTRADRLDACMDFRM+3;LOAD AUX2STASTRADR+1JSRDELAYJSRCMPLTJ }MPCMDXIT;OPERATION COMPLETE;CSEL07CMP#UPLOAD;UPLOAD COMMANDBNECSEL08;NOPE, TRY NEXT ONE;;THIS COMMAND WILL START } LOADING DATA;IN 256 BYTE CHUNKS STARTING AT THE;ADDRESS SET IN THE SET START ADDRESS;COMMAND. AFTER DATA HAS BEEN LOADED };THE START ADDRESS WILL BE INCREMENTED;BY ONE PAGE. IF IT IS POINTING TO;AN AREA OF MEMORY THAT DOES NOT EXIST;ON TE DUP }LICATOR, THEN AN ERROR IS;RETURNED;JSRDELAYJSRACKJSRULD;UPLOAD THE DATA FROM ATARI;;ULD RETURNS STATUS IN $A0 };JSRDELAYJSRACKJSRDELAYLDA:STATUS;CHECK STATUS FROM ULDCMP#2;MEMORY BOUND ERROR?BEQCMDERR;YES,SEND BAC }K ERRORCMP#1;CHECKSUM ERROR?BEQCMDNAK;SEND NACKJSRCMPLTJMPCMDXIT;CSEL08CMP#RUN;RUN PROGRAM COMMAND?BNEC }SEL09;NO, NEXT COMMAND;;DO AN INDIRECT JUMP TO ADDRESS PASSED;IN AUX1 AND AUX2. USER ROUTINE MUST;PERFORM AN RTS TO RET }URN TO CRET AND;MUST RETURN A STATUS IN MEM LOCATION;$A0 WHERE $00=OK, $02=ERROR;JSRDELAYJSRACKLDA#HIGH CRET;PUT } RETURN ADDRESSPHA;ONTO THE STACKLDA#LOW CRETPHALDACMDFRM+3PHA;PUSH ADDRESS ON STACK TOLDACMDFRM+2;JUMP T }OPHARTSCRETJSRDELAY;DO DELAYLDA:STATUS;GET STATUSCMP#2BEQCMDERRJSRCMPLT;STATUS OKJMPCMDXIT;CSEL09 }CMP#GTRACK;SEEK TRACK?BNECSEL10;NO NEXT COMMAND;;NEW TRACK NUMBER IS IN AUX1;JSRDELAY;WAIT A BITJSRACK;SEND }ACKLDA#41;CHECK FOR ILLEAGE TRACKCMPCMDFRM+2;COMPARE WITH AUX1BCCCMDERRLDACMDFRM+2STANTRKJSRSKTK;SEEK TR }ACKJSRCMPLT;SEND COMMPLETEJMPCMDXIT;CSEL10CMP#CFRMAT;CUSTOM FORMAT?BNECSEL11;;DO A USER SET CUSTOM FORMAT; }JSRDELAY;WAIT A BITJSRACKJSRCFMT;DO FORMATLDA:STATUS;CHECK STATUSBNECMDERR;ERROR IN FORMATJSRCMPLT;SEND } COMPLETEJMPCMDXIT;CSEL11JMP(CSELXX);USR DECODE ROUTINE;;COMMAND ERROR;CMDERRJSRDELAYJSRERRJMPCMDXIT;;B }AD COMMAND;;BAD COMMAND NAK;CMDNAKJSRDELAY;WAIT BEFORE NAK SENTJSRNAK;SEND NOT ACKNOLEDGE;CMDXITRTSLIST-LL !}INKD2:DD7M2.ASM************************;; THIS IS WHERE WE ENTER WHEN PROCESSOR; IS RESET.; PERIPHERAL DEVICES ARE INIT  DD7M2 ASM 139049 FREE SECTORS******;; THIS IS WHERE WE ENTER WHEN PROCESSOR; IS RESET.; PERIPHERAL DEVICES ARE INIT#;;*************************************;; ULD: UPLOAD PROGRAM DATA TO DUP BOARD;; ENTRY:STRADR SET BY SET ADDRESS; $} :COMMAND;; EXIT:STATUS ($A0) HOLDS STATUS; :0=OK 1=CHECKSUM ERROR; :2=MEMORY OUT OF RANGE ERROR;;**********%}****************************;ULDPROC;:STATUS=$A0;STATUS OF OPERATION:TEMP=$AF;TEMP MEMORY LOCATION;LDA#$00S&}TA:TEMPLDASTRADR+1CMP#$40;TOP OF MEMORY EXCEDED?BCC:ULD01;YES WE HAVE MEM ERRORLDA#$FFSTA:TEMP:ULD01LDA#'}0;SAVE VALUE OF LENTHLDXSTRADR;LOW BYTE OF POINTERSTXBPNTLDXSTRADR+1STXBPNT+1JSRREADLDA:TEMPBNE:ULD02(}INCSTRADR+1;ADD ONE TO UPLOAD ADRBNE:ULDXT:ULD02LDA#$02STA:STATUS:ULDXTRTSEPROC;;;************************)}*************;SINGLE DENSITY FD FORMAT;;*************************************;SFRMATJSRTRK0;HEAD TO TRACK 0LDA#39*}STANTRKJSRSKTKJSRTRK0JSRITRKS;MAKE SINGLE D TRACK IMAGETFORMBITSTREGBPLTF1BVCTF1JSRERR;SEND ERROR TO+} ATARIJMPFORM1;DEVICE NOT READY EXITTF1LDA#$00STABASE;RESET LOW BYTE OF POINTERLDA#$20STABASE+1;RESET HIGH ,}BYTELDY#0;CLEAR INDEXSTYDTAREG;INIT DATA REGLDA#1STAWT24E;LDX#100HOLDDEX;HOLD YOUR HORSES A BITBNEHOL-}D;JUST HUMOR ME, OK!;LDA#$F0;WRITE TRACK CMDSTACMDREGDRQYETBITDRABPLDRQYETSTYDTAREGDRYET1BITDRABPLDRY.}ET1STYDTAREGLDAWT64DLDA#$D1STAWT24E;RESET TIMER TO 208 MSTOUTBITDRABVCTRKERR;RETRY TRACK WRITEBPLTOUT/}LDA(BASE),YSTADTAREG;NEXT DATACLCLDA#1ADCBASESTABASELDA#0ADCBASE+1STABASE+1LDA#$C3CMPBASEBN0}ETOUTLDA#$2CCMPBASE+1BNETOUTTPADLDA#$01;MASK FOR BUSYLDX#0;DATA BYTETPAD1ANDSTREG;BUSY STATUS?BEQTDO1}NE;CMD GONEBITDRABPLTPAD1;WAIT FOR DATA REQUESTSTXDTAREG;PADDINGJMPTPAD1TDONELDASTREGAND#$04;LOST DATA?2}BEQTRKOK;GOOD TRACKTRKERRLDAWT64DJSRFINT;RETRY TRACK FORMATJMPTFORMTRKOKLDA#39CMPTRACKBEQFORM1INC$23}0C4INC$216FINC$221AINC$22C5INC$2370INC$241BINC$24C6INC$2571INC$261CINC$26C7INC$2772INC$281D4}INC$28C8INC$2973INC$2A1EINC$2AC9INC$2B74INC$2C1FLDA#$FFJSRSTEPT;GO TO NEXT TRACKJSRFINTJMPTFORM5}FORM1LDA#39STANTRKLDA#0STABPNT1;PNTR TO SECTOR INFOLDA#$20STABPNT1+1VRIFYJSRSKTKJSRVTRKDECNTRK6}BITNTRKBPLVRIFYJSRCMPLTJSRVDSKLDA#0STABPNT;PNTR TO SECTOR INFOLDA#$20STABPNT+1LDA#128JSRSENDRT7}S;;**************************************;; FORCE INTERRUPT;;**************************************;FINTLDA#$D0ST8}ACMDREGLDX#7FINT1DEXBNEFINT1LDA#1FINT2BITSTREGBNEFINT2RTS;**************************************; VTR9}K : VERIFY THAT A TRACK IS WRITTEN; CORRECTLY;ENTRY: NTRK = TRACK #; BPNT1 = PNTR TO SECTOR INFO;EXIT: B:}PNT1 POINTS TO BAD SECTOR INFO;**************************************VTRKLDA#0STABPNT;PNTR TO MODEL SECTORLDA#$2;}1STABPNT+1LDA#0TAYVT1STA(BPNT),YINYBEQVT1LDA#1STASECTVT2LDASECTJSRVSECBCCVT3LDA#18STAMLP<}LRLDANTRKSTAMCANDJSRMULTLDASECTSECSBC#1CLCADCPRODLDY#0STA(BPNT1),YLDAPROD+1ADC#0INCBPNT1=}STA(BPNT1),YINCBPNT1VT3INCSECTLDX#19CPXSECTBNEVT2LDY#0LDA#$FFSTA(BPNT1),YINYSTA(BPNT1),YRTS>};**************************************; MULT : 8 BIT MULTIPLY; ENTRY : MLPLR = MULTIPLIER; MCAND = MULTIPLICA?}ND; EXIT : PROD = 16 BIT PRODUCT;**************************************MULTLDA#0STAPROD+1LDX#8SHIFTASLAROL@}PROD+1ASLMCANDBCCCHCNTCLCADCMLPLRBCCCHCNTINCPROD+1CHCNTDEXBNESHIFTSTAPRODRTS;******************A}********************;; STEP TRACK; THIS ROUTINE WILL STEP ONE TRACK;; ENTRY:ACC=DIRECTION; :$00 = STEP FORWARD; B} :$FF = STEP BACKWARD;; EXIT:CARRY SET STEP ERROR; ;CARRY CLEAR OK;**************************************;STEPC}TPHA;SAVE COMMANDJSRTINC;INC TRACK COUNTERBCSSTEPTX;EXIT IF ERRORPLAPHAJSRSTEPPLAPHAJSRSTEPCLCSTEPD}TXPLARTS;;;**************************************;; STEPPER MOTOR ROUTINE; THIS ROUTINE ONLY STEPS A HALF A; A TRACE}K;; ENTRY:ACC=STEP DIRECTION; :$00=STEP FORWARD; ;$FF=STEP BACKWARD;; EXIT:NONE;;*************************F}*************;STEPPHA;SAVE COMMANDLDADRB;GET CURRENT STEP POSITIONORA#$C3;STRIP OFF OTHER BITSLDX#$00;SET INDG}EX COUNTSTEP21CMPSDAT,X;FIND ENTRY IN TABLEBEQSTEP22INX;NEXT ENTRYCPX#$05;ALL OUT OF ENTRIESBNESTEP21PLAH}SEC;SET ERROR FLAGBCSSTPXIT;EXIT FROM ROUTINE;STEP22PLA;GET COMMAND BACKCMP#$00;COMPARE DIRECTION?BNESTEP01;I}BACKWARD STEPINX;POINT TO NEXT ENTRYCPX#$05;IF XREG=5 THENBNESTEP23LDX#$01;XREG=1STEP23LDADRB;LOAD STEP DATJ}AORA#$3C;SET ALL BITS HIGHANDSDAT,X;SET ONE BIT LOWSTADRB;SET PORTJSRSWAIT;WAIT FOR 10mSECCLC;SET OK STATUK}SBCCSTPXITSTEP01DEX;POINT TO NEXT ENTRYCPX#$00;IF XREG=0 THENBNESTEP23LDX#$04;XREG = 4BNESTEP23STPXITRL}TS;EXIT POINT STEP;SDATDB$FF,$FB,$F7,$EF,$DF;STEP DATA;;**************************************;; TRACK INCREMENT ROM}UTINE;;**************************************;TINCPHACMP#0BEQTINC01INCTRACKLDATRACKCMP#40;FORTY TRACKS?N}BCCTINCXTLDA#39STATRACKSECBCSTINCXTTINC01DECTRACKLDATRACKCMP#$FFBNETINC02LDA#$00STATRACKSECO}BCSTINCXTTINC02CLCTINCXTPLARTS;;;**************************************;; READ DISK ADDRESS; RETURNS ADDRESS INP} SIX BYTE BLOCK; ON PAGE ZERO;;**************************************;RADRPHA;SAVE ACCTXAPHALDA#$06STARTRYSQ};SET NUMBER OF TRYS AT READRADR10LDX#$7ALDA#$80JSRSTMOLDX#$00;INDEX OF BLOCKLDA#$C0;LOAD READ ADRESS COMMANDR}STACMDREG;RADR01BITDRA;WATCH DATA READY FLAGBVCRADRXTBPLRADR01LDADTAREG;READ DATA REGISTERSTATADRES,XLS}DAWT64DINXCPX#$06;SIX BYTES YET?BNERADR01LDA#$01RADR03BITSTREGBNERADR03LDA#$08BITSTREGBEQRDRXIT;T}ALL SIX BYTES READ, EXITDECRTRYSBNERADR10SEC;SET CARRY TO IND. ERRORBCSRADRXT;;SIX BYTES READ, EXIT;RDRXITCLU}C;NO ERROR;RADRXTPLATAXPLARTS;;**************************************;; SWAIT:5 MSEC DELAY LOOP;; :PRESEV}RVES ALL REGISTERS;;**************************************;SWAITPHA;SAVE ACCUMULATORTXAPHA;SAVE X REGISTER;;9 CYW}CLES;LDA#$00STATEMP;;5 CYCLES;SWAIT1LDX#111;111 TIMESSWAIT0DEX;DECREMENT X REGDEXINXBNESWAIT0;;9 CYX}CLES * 111=999;INCTEMPLDATEMPCMP#$05BNESWAIT1;PLA;POP X REGTAXPLA;POP ACCUMULATOR;RTS;;**********Y}****************************; SEEK TRACK ZERO; PRESERVES ALL REGISTERS; AND INITIALIZES DISK ADDRESS;******************Z}********************TRK0PHA;SAVE ACCUMTXA;PUSH X REGPHATYA;PUSH Y REGPHAJSRFINT;FORCE INTERRUPTLDA#39S[}TATRKREGSTATRACKTRK001LDA#$00JSRSTEP;STEP DRIVELDASTREGAND#$04BNETRK001LDA#$00JSRSTEP;STEP ONE MOR\}E BACKWARDSLDA#$00JSRSTEP;STEP ONE BACKWARDLDA#$FFJSRSTEP;STEP ONE FORWARDLDA#0STATRACKCLCPLATAYP]}LATAXPLARTS;;**************************************;; SEEK TRACK;; ENTRY:NTRK = TRACK NUMBER TO SEEK;; EXIT:CA^}RRY SET IF TRACK NOT FOUND;;;**************************************;SKTKLDANTRKCMPTRACK;NEW TRACK?BEQSKTK02;TR_}ACK FOUND, EXIT OKBCSSKTK01;NEW TRACK IS LESSLDA#$00;STEP FORWARDJSRSTEPT;STEP A TRACKBCCSKTK;IF NO ERROR, LO`}OPBCSSKTXIT;ERROR IN STEPINGSKTK01LDA#$FF;STEP THE OTHER WAYJSRSTEPT;STEP A TRACKBCCSKTK;IF OK, KEEP LOOPINGa}BCSSKTXIT;ERROR IN STEPPINGSKTK02CLCSKTXITRTS;;;**************************************;; CALCULATE NEW TRACK/SECTb}OR NUMBER;; ENTRY:ATARI SECTOR NUMBER IN; :CMDFRM+2 AND CMDFRM+3; EXIT:TRACK NUMBER IN; :NTRK AND SECTOR NUMBc}ER; :IN NSEC CMDFRM+2 AND +3 ARE; :DESTROYED;; SAVES NO REGISTERS;;**************************************;d};SUBTRACT ONE FROM TRAK NUMBER;NTSSEC;PREPARE TO SUBTRACTLDACMDFRM+2SBC#$01STACMDFRM+2LDACMDFRM+3SBC#$00e}STACMDFRM+3BCCNTSERR;SECTOR NUMBER ERROR;;CALCULATE TRACK/SECTOR;ACCL=CMDFRM+2ACCH=CMDFRM+3;LDA#18;NUMBER f}OF SECTORS PER TRACKSTATEMPLDY#8;NUMBER OF BITS TO DIVIDE BYASLACCLUDIV1ROLACCH;SHIFT DIVIDENDBCSUDIV2;JMP g}IF 1 SHFTD OUT OF DVDNDLDAACCH;SUBTRACT DIVISOR FROM ACCHSECSBCTEMPBCCUDIV4;JMP TO SHIFT AND COUNT IF;UNDEFLq} b'DOS SYSb*+DUP SYSbCUDD7M0 ASMbDD7M1 ASM"DD7M2 b#DD7M2 ASMbDD7M3 ASMOW IS IMMENIENT,CARRY;IS QUOTIENT BITSTAACCH;STORE DIFF IF NO UNDEFLOW;FLAG IS QUOTIENT BITBCSUDIV4;UDIV2LDr}AACCH;SUBTRACT DVSR FRM ACCH;SBCTEMPBCSUDIV3;SKIP IF UNDERFLOW IMMENIENTSTAACCHSECBCSUDIV4UDIV3CLC;QUOTIEs}NT BIT IS ZEROUDIV4ROLACCL;SHIFT DIVIDENT LOW PARTDEY;COUNT INTERATIONSBNEUDIV1;LDAACCLSTANTRK;STORE NEW TRt}ACK NUMBERLDAACCHSTANSEC;NEW SECTORINCNSEC;NSEC==+1CLCBCCNTSXITNTSERRSECNTSXITRTS;*********************u}*****************;; READ SECTOR FROM DISK;; ENTRY:ACC=SECTOR NUMBER; :BUFFER POINTER POINTS TO SECTOR; :BUFFEv}R WHERE DATA IS TO BE PUT; EXIT:CARRY SET IF ANY ERROR;;**************************************RSECPROC;:STATUS=$A0w};STASECREG;STORE IN SECTOR REGLDATRACKSTATRKREG;SET UP TRACK REGISTERLDA#$00STAECRSEC12LDY#$00;SET UP Ix}NDEX POINTERLDX#$00LDA#$E6JSRSTMO;SET TIME OUTLDA#$82;READ SECTOR COMMANDSTACMDREG;PUT INTO COMMAND REGISTEy}RRSEC01BITDRA;TEST STATUSBVCRSEC10;TIMEOUTBPLRSEC01;DATA NOT READY YETLDADTAREG;LOAD DATA REGISTEREOR#$FFz};COMPLEMENT DATASTA(BPNT),Y;STORE IN BUFFERLDAWT64D;CLEAR TIMEOUT COUNTERINYCPYLENTH;COMPARE LENTH OF SECTORB{}NERSEC01;NOT DONE KEEP GETTING DATALDA#$01;MASK FOR FDCRSEC02BITSTREG;CHECK FDC STATUSBNERSEC02LDASTREGLDA|}#0STA:STATUS;RETURN GOOD STATUSCLCRSECXTRTSRSEC10LDASTREGAND#$01BEQRSEC11LDA#$E6JSRSTMO;SET TIMEOUT}}BNERSEC01RSEC11LDAWT64DINCECLDASTREGAND#$04;CHECK FOR LOST DATABNERSEC12LDA#$01STA:STATUS;SET YUCKY S~}TATUSSECBCSRSECXT;ERROR EXITEPROC;;**************************************;; VERIFY SECTOR JUST READ;; ENTRY:ACC}=SECTOR NUMBER; :BUFFER POINTER POINTS TO SECTOR; :BUFFER WHERE DATA IS TO BE PUT; EXIT:CARRY SET IF ANY ERROR};;**************************************VSECPROC;:STATUS=$A0;STASECREG;STORE IN SECTOR REGLDATRACKSTATRKRE}G;SET UP TRACK REGISTERLDA#$00STAECSTATEMP;CLEAR FLAGVSEC1LDY#$00;SET UP INDEX POINTERLDX#$00LDA#$E6JS}RSTMO;SET TIME OUTLDA#$82;READ SECTOR COMMANDSTACMDREG;PUT INTO COMMAND REGISTERVSEC2BITDRA;TEST STATUSBVCVS}EC6;TIMEOUTBPLVSEC2;DATA NOT READY YETLDADTAREG;LOAD DATA REGISTEREOR#$FF;COMPLEMENT DATACMP(BPNT),Y;COMPARE} WITH BUFFERBEQVSEC3;DATA OKLDA#$FFSTATEMP;SET FLAGVSEC3LDAWT64DINYCPYLENTH;COMPARE LENTH OF SECTORBNE}VSEC2;NOT DONE KEEP GETTING DATALDA#$01;MASK FOR FDCVSEC4BITSTREG;CHECK FDC STATUSBNEVSEC4LDASTREGLDA#0;SE}T GOOD STATUSSTA:STATUSCLCVSEC5LDATEMP;LOAD FLAGBPLVSECXT;DATA OKLDA#$01STA:STATUS;SET BAD STATUSSECB}CSVSECXT;BAD READVSEC6LDASTREGAND#$01BEQVSEC7LDA#$E6JSRSTMO;SET TIMEOUTBNEVSEC2VSEC7LDAWT64DINCEC}LDASTREGAND#$04;CHECK FOR LOST DATABNEVSEC1LDA#$01STA:STATUSSECVSECXTRTSEPROC;;***********************}***************;; READ TRACK ROUTINE;; ENTRY:NONE; EXIT:CARRY SET IF ERROR; :$A0 = # OF BAD SECTORS;************}**************************RDTKPROC;:STATUS=$A0:COUNT=$A5;COUNT OF GOOD SECTORS;LDATINBCMP#$FF;BUFFER EMPTY}?BEQRDTK02;YES READ TRACKCMPNTRK;IS NEW TRACK DIFFERENT?BNERDTK02CLC;CLEAR CARRY FOR OKBCCRDTKXTRDTK02PHA}LDX#0TXASTA:COUNT;INIT GOOD SECTOR COUNTRDTK05STATRKCH,X;CLEAR SECTOR STATUSINXCPX#18BNERDTK05PLALDX}#$00;SKEW INDEX INITRDTK01TXAPHALDASECSK,X;SECTOR NUMBERJSRSBPNT;SET BUFFER POINTERJSRRSEC;READ IN SECTORP}LATAXLDA:STATUSBEQRDTK04INC:COUNTLDA#$FFSTATRKCH,X;BAD SECTOR FLAG SETRDTK04INX;NEXT SECTORCPX#18;E}IGHTEEN SECTORS?BEQRDTK03LDASECSK,X;LOAD SECTORJSRSBPNTJMPRDTK01RDTK03LDANTRKSTATINB;SET TRACK IN BUFFER }IND.CLCRDTKXTLDA:COUNTSTA:STATUSRTSEPROC;SECSKDB1,5,9,13,17,4,8,12,16,3,7,11,15,2,6,10,14,18;;*************}*************************;; SET BUFFER POINTER TO MEMORY PAGE FOR; SECTOR; ENTRY:ACC=SECTOR NUMBER; EXIT:BPNT=PAGE POIN}TER;; ALL REGISTERS PRESERVED;;**************************************;SBPNTPHASECSBC#$01CLCADC#HIGH BUFFST}ABPNT+1LDA#$00STABPNTPLARTS;;**************************************; READ SECTOR;; ENTRY:NONE; EXIT:CARRY S}ET IF ERROR;;**************************************;RDSCLDANSECJSRSBPNTLDALENTH;LENTH OF SECTORJSRSENDRTS;};**************************************;; TURN ON DRIVE MOTOR;; ENTRY:NONE; EXIT:NONE;; PRESERVES ALL USED REGISTERS};;**************************************;MOONPHALDADRA;LOAD DATA REGISTERAND#$F7;SET CONTROLL BIT LOWSTADRA;}FOR MOTORLDA#$FFSTAMFLAG;SET MOTOR ON FLAGPLARTS;;**************************************;; TURN OFF DRIVE MOTO}T;; ENTRY:NONE; EXIT:NONT;; PRESERVES ALL REGISTERS;;**************************************;MOOFFPHALDADRA;LOA}D DATA REGISTERORA#$08;SET MOTOR CONTROL BIT HIGHSTADRAPLARTS;;**************************************;; INIT 5} SECOND TIMER;; ENTRY:NONE; EXIT:NONE;; PRESERVES ALL REGISTERS;;**************************************;I5SECPHA}LDA#$11;TIME COUNTSTATCLDA#$FFSTAWT24E;STORE IN TIME ENABLE IRQPLARTS;;************************************}**;; CHECK 5 SECOND TIMER;; ENTRY:NONE; EXIT:CARRY SET IF TIMED OUT;; PRESERVES ALL REGISTERS;;********************}******************;CK5SPHABITDRA;CHECK FOR TIMER TIMEOUTBVSCK5SXTDECTC;DECREMENT TIMER COUNTLDATCBEQCK5S0}1;COUNT ENDEDLDA#$FFSTAWT24E;RESET TIMERCLCBCCCK5XITCK5S01LDARTDE;DISABLE TIMERSECBCSCK5XITCK5SXTCLC}CK5XITPLARTS;;**************************************;; WRITE SECTOR;; ENTRY:ACC=SECTOR TO WRITE; :BUFFER POINT}ER POINTS TO DATA; EXIT:CARRY SET IF ANY ERRORS;;**************************************;WSECPROC;:STATUS=$A0;ST}ASECREGLDATRACKSTATRKREG;SET UP SECTOR TO WRITE TOWSEC01LDY#$00LDX#$00LDA#$E6JSRSTMOLDA#$A2;WRITE SEC}TOR COMMANDSTACMDREGWSEC02LDA(BPNT),YEOR#$FF;LOAD AND COMPLEMENT DATAWSEC03BITDRA;CHECK FOR WHEN FDC REDYBVC}WSEC10;TIME OUT ERRORBPLWSEC03;LOOP UNTIL READYSTADTAREG;SEND DATA TO FDCLDAWT64DINYCPYLENTH;COMPARE WITH S}ECTOR LENTHBNEWSEC02LDA#$01WSEC04BITSTREGBNEWSEC04;LOOP UNTIL DONELDASTREGLDA#0STA:STATUS;SET STATUS O}K!CLCRTSWSEC10LDASTREGAND#$01;CHECK FOR BUSYBEQWSEC20LDA#$E6JSRSTMOBNEWSEC02WSEC20LDAWT64DLDASTR}EGAND#$04;CHECK FOR LOST DATABNEWSEC01LDASTREGLDA#$01STA:STATUS;SET STATUS YUCKY!SECRTSEPROC;;******}********************************;ITRKS : INITIALIZE A SINGLE DENSITY;TRACK BY SETTING UP A MODEL TRACK;IN RAM AT LOC}ATION $2000;ENTRY : SECT IS SECTOR #; TRCK IS TRACK #;EXIT : MODEL TRACK AT $2000;**************************}************ITRKSLDA#$00STABASELDA#$20STABASE+1;COPY BASE POINTERLDY#0;INITIALIZE INDEXLDX#$AC;# OF BY}TES TO LOOPLDA#0;INIT BYTES TO $FFTKHDR1DEX;DECREMENT LOOP COUNTSTA(BASE),Y;STORE DATAINYCPX#0;STOP LOOP?}BNETKHDR1LDA#$FC;INIT BYTE TO $FCSTA(BASE),Y;STORE DATAINY;UPDATE BASE INDEXLDX#16LDA#0TKHDR3DEXSTA}(BASE),YINYCPX#0BNETKHDR3;END OF TRACK HEADER?LDX#1STXSECT;SECT IS SECTOR #; BEGIN SECTOR FORMAT MODEL; }UPDATE BASE POINTERSHDR1STYTEMPLDABASECLCADCTEMPSTABASELDABASE+1;IF THIS DOESN'T ALTER C,ADC#0;THEN AD}D CARRY IF ANYSTABASE+1LDY#0LDX#6;6 BYTESLDA#0;LOAD 0SHDR2DEXSTA(BASE),YINYCPX#0BNESHDR2LDA#$}FESTA(BASE),YINYLDATRCK;TRACK #STA(BASE),YINYLDA#0;SIDE #STA(BASE),YINYLDASECT;SECTOR #STA(B}ASE),YINYLDA#0;SECTOR LENGTH = 128STA(BASE),YINYLDA#$F7;FOR 2 BYTE CRCSTA(BASE),YINYLDX#17;11 BYTE}SLDA#0;LOAD $FFSHDR3DEXSTA(BASE),YINYCPX#0BNESHDR3LDA#$FBSTA(BASE),YINYLDX#128LDA#$FFSDATA}DEXSTA(BASE),YINYCPX#0BNESDATALDA#$F7STA(BASE),YINYLDX#12LDA#0SECENDDEXSTA(BASE),YINYCPX}#0BNESECENDLDASECTCMP#18;DONE WITH ALL 18 SECTORS?BEQTRKPAD;YES, NOW PAD TRACKINCSECT;INCREMENT SECTOR COU}NTJMPSHDR1TRKPADRTS;DONE WITH TRACK IMAGE!;**********************************; DISK MAP;**************************}********VDSKLDA#0STABPNTLDA#$20STABPNT+1LDA#$FFLDY#0STA(BPNT),YINYSTA(BPNT),YLDA#0VDSK1INYST}A(BPNT),YCPY#128BNEVDSK1RTS;LINKD2:DD7M3.ASMOGRAM DATA TO DUP BOARD;; ENTRY:STRADR SET BY SET ADDRESS; ;;LIST*;;**************************************;; CUSTOM FORMATING ROUTINES; INCLUDE COMAND 'c' and 's'; 'c'= Write c}ustom buffer to current; track; 's'= Seek track given in Aux1;;**************************************;; CFMT: CU}STOM FORMAT TRACK;; ENTRY:IT IS ASSUMED THAT THE BUFFER; :STARTS AT $2000; :BUFFER WAS LOADED USING THE; }:THE DOWNLOAD COMMAND; :AUX1 AND AUX2 CONTAIN #OF BYTES; :USES BPNT TO POINT TO BUFFER; :SETUP THE DENSITY }LINE ON THE; :FDC FOR SINGLE DENSITY ON ENTRY; :RETURNS IT TO WHAT EVER ON EXIT; EXIT:NONE, DOES NOT CHECK FOR }ANY; :ERRORS;;**************************************;CFMTPROC;:STATUS=$A0;LDA#$00STARTRYS;INT RETRY CO}UNTER;;CHECK TO SEE IF DOOR IS OPEN;BPL:CFT01BVC:CFT01LDA#$01;SET ERROR STATUSJMP:CFTXT;EXIT ROUTINE;:CFT0}1LDY#$00LDA#$00;SET UP BPNT TO POINT TOSTABPNT;CUSTOM DATA IN TRACK BUFFERLDA#$20STABPNT+1LDA(BPNT),YJSR}IBPNT;INCREMENT POINTERSTADTAREG;FIRST BYTE OF TRACK DATALDA#1STAWT24E;START TIMER TO GEN IPLDX#$10:LOOPDEX}BNE:LOOP;JUST DELAY A BIT, HUMOR MELDA#$F0;FORMAT COMMANDSTACMDREG:WAITBITDRA;WAIT FOR FIRST DRQBPL:WAITL}DA(BPNT),YSTADTAREG;PUT DATA INTO DATA REGJSRIBPNT;INCREMENT POINTER:WAIT1BITDRA;WAIT FOR SECOND DRQBPL:WAIT1}LDA(BPNT),YSTADTAREGLDAWT64D;CLEAR IP PULSELDA#$D1;SET TIME FOR DISK ROTATIONSTAWT24E;OF 208 MSJSRIBPNT};INCREMENT POINTER:LOOP1BITDRA;WAIT FOR DRQBVC:CFTER;TIMEOUT ERROR, RETRYBPL:LOOP1LDA(BPNT),YSTADTAREGJSR}IBPNT;INCREMENT BPNTLDABPNT+1;END OF BUFFER?CMPCMDFRM+3BCC:CFT02BNE:CFT02LDABPNTCMPCMDFRM+2:CFT02BNE:L}OOP1LDA#$01;MASK FOR BUSYLDX#0;DATA TO DISK:CFT03ANDSTREG;FDC BUSY?BEQ:CFT04;DONEBITDRA;WAIT FOR DATA REQ}UESTBPL:CFT03;WAIT FOR DRQSTXDTAREGBMI:CFT03:CFT04LDASTREGAND#$04;CHECK FOR LOST DATABEQ:CFT05;TRACK OK,} WE HOPE:CFTERLDAWT64D;CLEAR IPJSRFINT;CLEAR FDCINCRTRYS;INCREMENT RETRYSLDA#$06CMPRTRYS;SIX TIMES?BEQ:}CFT06JMP:CFT01;NOPE TRY AGAIN;:CFT06LDA#$01STA:STATUS;SET BAD STATUSBNE:CFTXT;GOODBY:CFT05LDA#0STA:STAT}US;GOOD STATUS:CFTXTJSRFINTRTSEPROC;;**************************************;; IBPNT: INCREMENT BPNT;; ENTRY:NON}E; EXIT:BPNT INCREMENTED BY ONE;;**************************************;IBPNTPROC;INCBPNTBNE:IBPTX;INCREMENT I}F NO OVER FLOWINCBPNT+1:IBPTXRTSEPROC;ENDSTARTTOM FORMATING ROUTINES; INCLUDE COMAND 'c' and 's'; 'c'= Write c;